<?php
/**
 * 积分服务
 * 
 * 提供积分获取、积分设置等服务
 * 
 * @author thinksns
 *
 */
class PayProviderService extends Service {
	
	/**
	 * 处理组装参数，返回转到对应的支付服务提供商的js代码。
	 * @param unknown_type $provider_type		支付服务提供商代码目前支持alipay tenpay
	 * @param unknown_type $out_trade_no		系统内部订单号
	 * @param unknown_type $subject				订单对应的标题
	 * @param unknown_type $body				相对详细写的订单简单描述（tenpay中用不到这个描述）
	 * @param unknown_type $total_fee			总金额（单位元）（tenpay单位为分，相应gototenpay方法内部以作转换）
	 * @param unknown_type $pay_mode			支付方式tenpay为财付通   其他alipay或银行代码为支付宝支付。
	 * @param unknown_type $itemType			表示具体充值相类型：对应数据字典付款类型。因支付相不止订单，还可能充值。
	 * 
	 */
	public function gotoPayProvider($out_trade_no,$subject,$body,$total_fee,$pay_mode,$itemType=''){
		
		$result['status'] = 1;
		if($pay_mode=='tenpay'){
			$result['data']=$this->gototenpay($out_trade_no,$subject,$body,$total_fee,$pay_mode,$itemType);
		}else{
			$result['data']=$this->gotoalipay($out_trade_no,$subject,$body,$total_fee,$pay_mode,$itemType);
		}
		return $result;
	}
	
private function dealTenpayResult(){
		//---------------------------------------------------------
		//财付通即时到帐支付应答（处理回调）示例，商户按照此文档进行开发即可
		//---------------------------------------------------------
		require_once (PAY_LIB_PATH."/tenpay/classes/PayResponseHandler.class.php");
		$paymentconf = (include K_CONFIG_PATH.'config_payment.php');
		$tenpay_config = $paymentconf['tenpay_config'];
		/* 密钥 */
		$key = $tenpay_config['key'];
		
		/* 创建支付应答对象 */
		$resHandler = new PayResponseHandler();
		$resHandler->setKey($key);
		
		//判断签名
		if($resHandler->isTenpaySign()) {
			
			//交易单号
			$transaction_id = $resHandler->getParameter("transaction_id");
			
			//金额,以分为单位
			$total_fee = $resHandler->getParameter("total_fee");
			
			//支付结果
			$pay_result = $resHandler->getParameter("pay_result");
			
			$attach = $resHandler->getParameter("attach");
			$sp_billno = $resHandler->getParameter("sp_billno");
			if( "0" == $pay_result ) {
			
				//------------------------------
				//处理业务开始
				//------------------------------
				
				//由于财付通金额单位为分，系统内部的所有金额单位为元。
				//所以做此转换，转换为元为单位。
				$total_fee = $total_fee/100;
				$total_fee = sprintf("%01.2f",$total_fee);
				
				//注意交易单不要重复处理
				//注意判断返回金额
				$result = $this->addPayInfo('tenpay',$transaction_id,$attach,$sp_billno,$total_fee,serialize($_GET));
				//------------------------------
				//处理业务完毕
				//------------------------------	
				if($result['status']==1){
				//调用doShow, 打印meta值跟js代码,告诉财付通处理成功,并在用户浏览器显示$show页面.
					$show = $tenpay_config['pay_result_url'];
					$strHtml = $resHandler->doShow($show);
					$result['data'] = $strHtml;
				}else{
					$result['data'] = "<br/>" . "支付失败".$result['msg']. "<br/>";
				}
			
			} else {
				//当做不成功处理
				$result['status'] = -1;
				$result['data'] = "<br/>" . "支付失败" . "<br/>";
			}
			
		} else {
			$result['status'] = -1;
			$result['data'] = "<br/>" . "认证签名失败" . "<br/>";
		}	
		return $result;
	}
	
	
	private function dealAlipayResult(){
		require_once(PAY_LIB_PATH."/alipay/class/alipay_notify.php");
		//require_once(PAY_LIB_PATH."/alipay/alipay_config.php");
		$paymentconf = (include K_CONFIG_PATH.'config_payment.php');
		extract($paymentconf['alipay_config']);
		//构造通知函数信息
		$alipay = new alipay_notify($partner,$key,$sign_type,$_input_charset,$transport);
		//计算得出通知验证结果
		$verify_result = $alipay->return_verify();
		
		if($verify_result){
			//验证成功
			//*********************************************************************************
			//请在这里加上商户的业务逻辑程序代码
			$dingdan        = $_GET['out_trade_no'];    //获取订单号
			$total_fee      = $_GET['total_fee'];	    //获取总价格
			$trade_no		= $_GET['trade_no'];
			$itemType		= $_GET['extra_common_param'];
			
			if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {
				//支付数据录入成功后，作相应处理。主要是一些提示信息。
				//若为充值则记录充值新增记录。
				$result = $this->addPayInfo('alipay',$trade_no,$itemType,$dingdan,$total_fee,serialize($_GET));
				//如果有做过处理，不执行商户的业务程序
			}else {
				//echo "trade_status=".$_GET['trade_status'];
				unset($result);
				$result['status']=0;
				$result['msg']='支付服务提供商返回结果：支付失败！';
			}
			//——请根据您的业务逻辑来编写程序（以上代码仅作参考）
				
			//*********************************************************************************
		}
		else {
		    //验证失败
		    //如要调试，请看alipay_notify.php页面的return_verify函数，比对sign和mysign的值是否相等，或者检查$veryfy_result有没有返回true
		    unset($result);
		    $result['status']=0;
			$result['msg']='支付服务提供商返回结果：支付失败！';
		}
		return $result;
	}
	
	/**
	 * 由于现金账户支付的特殊性，提供此方法。
	 * @param unknown_type $out_trade_no
	 * @param unknown_type $itemType
	 */
	public function dealXxypayResult($out_trade_no,$itemType){
		$orderinfo = service('Order')->get4UserById($out_trade_no);
		$uamount = service('UserAccount')->get4User();
		$result['data']=$uamount;
    	if($uamount['current_money']<$orderinfo['paid_money']){
    		$result['status']=0;
    		$result['msg']="现金帐户支付失败！账户余额不足，请充值！";
    		return $result;
    	}
		//直接录入支付数据
		$ary_payinfo=array(	'trade_no'=>''//当用现金账户支付时，交易Id将在录入前自动维护
	 									,'pay_type'=>$itemType
		 								,'item_id'=>$out_trade_no
										,'total_fee'=>$orderinfo['paid_money']
		 								,'service'=>'xxypay'
		 								,'return_info'=>''
		 								,'paytime'=>time()
		  								,'uid'=>$orderinfo['user_id']
		 							);
		//unset($result);
		$result1 = service('Pay')->addPayInfo($ary_payinfo);
		$result['PayInfo']=$ary_payinfo;
		if($result1['status']==1){
		 	service('UserAccount')->refresh4UserCash();
		 	$result['status']=1;
			$result['msg']="支付成功！支付金额：".$orderinfo['paid_money'].' 元！';
		 }else{
		 	$result['status']=0;
			$result['msg']="现金帐户支付失败！".$result1['msg'];
		}
		return $result;
	}
	
	
	/**
	 * 处理第三方支付结果。按照第三方接口返回相应结果。
	 * @param unknown_type $pay_mode	支付方式tenpay为财付通   alipay为支付宝。
	 */
	public function dealPayResult($pay_mode){
		if($pay_mode=='alipay'){
			$result=$this->dealAlipayResult();
		}else if($pay_mode=='tenpay'){
			$result=$this->dealTenpayResult();
		}else{
			$result['status']=-1;
			$result['msg']='找不到对应的支付服务提供商！';
		}
		return $result;
	}
	
	
	private function gotoalipay($out_trade_no,$subject,$body,$total_fee,$pay_mode,$itemType){
		if($pay_mode=='aliypay'){
			$pay_mode = "directPay";
		}
		////////////////////注意/////////////////////////
		//如果您在接口集成过程中遇到问题，
		//您可以到商户服务中心（https://b.alipay.com/support/helperApply.htm?action=consultationApply），提交申请集成协助，我们会有专业的技术工程师主动联系您协助解决，
		//您也可以到支付宝论坛（http://club.alipay.com/read-htm-tid-8681712.html）寻找相关解决方案
		//要传递的参数要么不允许为空，要么就不要出现在数组与隐藏控件或URL链接里。
		/////////////////////////////////////////////////
		$extra_common_param = $itemType;
		//require_once( PAY_LIB_PATH."/alipay/alipay_config.php");
		require_once( PAY_LIB_PATH."/alipay/class/alipay_service.php");
		$paymentconf = (include K_CONFIG_PATH.'config_payment.php');
		extract($paymentconf['alipay_config']);
		if($itemType=='pay_charge'){
			$show_url='';
		}
		/*以下参数是需要通过下单时的订单数据传入进来获得*/
		//必填参数
		//$out_trade_no = $itemid;		//请与贵网站订单系统中的唯一订单号匹配
		//$subject      = $itemid;	//订单名称，显示在支付宝收银台里的“商品名称”里，显示在支付宝的交易管理的“商品名称”的列表里。
		//$body         = $_POST['alibody'];	//订单描述、订单详细、订单备注，显示在支付宝收银台里的“商品描述”里
		//$total_fee    = $_POST['alimoney'];	//订单总金额，显示在支付宝收银台里的“应付总额”里
		
		//扩展功能参数——默认支付方式
		//$pay_mode	  = $_POST['pay_bank'];
		if ($pay_mode == "directPay") {
			$paymethod    = "directPay";	//默认支付方式，四个值可选：bankPay(网银); cartoon(卡通); directPay(余额); CASH(网点支付)
			$defaultbank  = "";
		}
		else {
			$paymethod    = "bankPay";		//默认支付方式，四个值可选：bankPay(网银); cartoon(卡通); directPay(余额); CASH(网点支付)
			$defaultbank  = $pay_mode;		//默认网银代号，代号列表见http://club.alipay.com/read.php?tid=8681379
		}
		
		
		//扩展功能参数——防钓鱼
		//请慎重选择是否开启防钓鱼功能
		//exter_invoke_ip、anti_phishing_key一旦被使用过，那么它们就会成为必填参数
		//开启防钓鱼功能后，服务器、本机电脑必须支持远程XML解析，请配置好该环境。
		//若要使用防钓鱼功能，请打开class文件夹中alipay_function.php文件，找到该文件最下方的query_timestamp函数，根据注释对该函数进行修改
		//建议使用POST方式请求数据
		$anti_phishing_key  = '';			//防钓鱼时间戳
		$exter_invoke_ip = '';				//获取客户端的IP地址，建议：编写获取客户端IP地址的程序
		//如：
		//$exter_invoke_ip = '202.1.1.1';
		//$anti_phishing_key = query_timestamp($partner);		//获取防钓鱼时间戳函数
		
		//扩展功能参数——其他
		//$extra_common_param = '';			//自定义参数，可存放任何内容（除=、&等特殊字符外），不会显示在页面上
		$buyer_email		= '';			//默认买家支付宝账号
		
		//扩展功能参数——分润(若要使用，请按照注释要求的格式赋值)
		$royalty_type		= "";			//提成类型，该值为固定值：10，不需要修改
		$royalty_parameters	= "";
		//提成信息集，与需要结合商户网站自身情况动态获取每笔交易的各分润收款账号、各分润金额、各分润说明。最多只能设置10条
		//各分润金额的总和须小于等于total_fee
		//提成信息集格式为：收款方Email_1^金额1^备注1|收款方Email_2^金额2^备注2
		//如：
		//royalty_type = "10"
		//royalty_parameters	= "111@126.com^0.01^分润备注一|222@126.com^0.01^分润备注二"
		
		
		/////////////////////////////////////////////////
		
		//构造要请求的参数数组，无需改动
		$parameter = array(
	        "service"			=> "create_direct_pay_by_user",	//接口名称，不需要修改
	        "payment_type"		=> "1",               			//交易类型，不需要修改
	
	        //获取配置文件(alipay_config.php)中的值
	        "partner"			=> $partner,
	        "seller_email"		=> $seller_email,
	        "return_url"		=> $return_url,
	        "notify_url"		=> $notify_url,
	        "_input_charset"	=> $_input_charset,
	        "show_url"			=> $show_url,
	
	        //从订单数据中动态获取到的必填参数
	        "out_trade_no"		=> $out_trade_no,
	        "subject"			=> $subject,
	        "body"				=> $body,
	        "total_fee"			=> $total_fee,
	
	        //扩展功能参数——网银提前
	        "paymethod"			=> $paymethod,
	        "defaultbank"		=> $defaultbank,
	
	        //扩展功能参数——防钓鱼
	        "anti_phishing_key"	=> $anti_phishing_key,
			"exter_invoke_ip"	=> $exter_invoke_ip,
	
			//扩展功能参数——自定义参数
			"buyer_email"		=> $buyer_email,
	        "extra_common_param"=> $extra_common_param,
			
			//扩展功能参数——分润
	        "royalty_type"		=> $royalty_type,
	        "royalty_parameters"=> $royalty_parameters
		);
		
		//构造请求函数
		$alipay = new alipay_service($parameter,$key,$sign_type);
		$sHtmlText = $alipay->build_form();
 		return $sHtmlText;
	}
	
	
	private function gototenpay($out_trade_no,$subject,$body,$total_fee,$pay_mode,$itemType){
		$extra_common_param = $itemType;
		$paymentconf = (include K_CONFIG_PATH.'config_payment.php');
		require_once (PAY_LIB_PATH."/tenpay/classes/PayRequestHandler.class.php");
		$tenpay_config = $paymentconf['tenpay_config'];
		
		/* 商户号 */
		$bargainor_id = $tenpay_config['bargainor_id'];
		
		/* 密钥 */
		$key = $tenpay_config['key'];
		
		/* 返回处理地址 */
		$return_url = $tenpay_config['return_url'];
		
		
		
		/* 商家订单号,长度若超过32位，取前32位。财付通只记录商家订单号，不保证唯一。 */
		$sp_billno = $out_trade_no;
		
		
		//date_default_timezone_set(PRC);
		$strDate = date("Ymd");
		$strTime = date("His");
		//4位随机数
		$randNum = rand(1000, 9999);
		//10位序列号,可以自行调整。
		$strReq = $strTime . $randNum;
		/* 财付通交易单号，规则为：10位商户号+8位时间（YYYYmmdd)+10位流水号 */
		$transaction_id = $bargainor_id . $strDate . $strReq;
		
		
		/* 商品价格（包含运费），以分为单位 */
		$total_fee = $total_fee*100;//由于传过来的金额是以元为单位。
		
		/* 商品名称 */
		$desc = $subject;
		
		/* 创建支付请求对象 */
		$reqHandler = new PayRequestHandler();
		$reqHandler->init();
		$reqHandler->setKey($key);
		
		//----------------------------------------
		//设置支付参数
		//----------------------------------------
		$reqHandler->setParameter("bargainor_id", $bargainor_id);			//商户号
		$reqHandler->setParameter("sp_billno", $sp_billno);					//商户订单号
		$reqHandler->setParameter("transaction_id", $transaction_id);		//财付通交易单号
		$reqHandler->setParameter("total_fee", $total_fee);					//商品总金额,以分为单位
		$reqHandler->setParameter("return_url", $return_url);				//返回处理地址
		$reqHandler->setParameter("desc", $desc);	//商品名称
		$reqHandler->setParameter("cs", $tenpay_config['cs']);	//字符编码标准，gbk或者utf-8
		$reqHandler->setParameter("attach",$extra_common_param);	//商家数据包，原样返回
		
		//用户ip,测试环境时不要加这个ip参数，正式环境再加此参数
		$reqHandler->setParameter("spbill_create_ip", $_SERVER['REMOTE_ADDR']);
		
		//请求的URL
		$reqUrl = $reqHandler->getRequestURL();
		
		//debug信息
		//$debugInfo = $reqHandler->getDebugInfo();
		
		//echo "<br/>" . $reqUrl . "<br/>";
		//echo "<br/>" . $debugInfo . "<br/>";
		
		//重定向到财付通支付
		//$reqHandler->doSend();
		$sHtmlText = "<script>window.location.href = '".$reqUrl."';</script>";
		//$sHtmlText = '<a href="'.$reqUrl.'" target="_blank">财付通支付</a>'.$reqUrl;
		return $sHtmlText;
		
	}
	
	
	private function addPayInfo($pay_mode,$trade_no,$itemType,$out_trade_no,$total_fee,$serialize_return_info){
		$_uid = "";
		$_total_pay = 0;//计算已支付金额
		if($itemType=='pay_order'){
			$order = service('Order')->get4SysById($out_trade_no);
			$_total_pay = service('Pay')->countOrderPaiedAmount($out_trade_no,'pay_order','Y','Y');
			$error_msg = "";
			//判断该笔订单是否在商户网站中已经做过处理（可参考“集成教程”中“3.4返回数据处理”）
			//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
			//判断订单
			if(empty($order))$error_msg='订单不存在！';
			$_uid = $order['user_id'];
					
		}else if($itemType=='pay_charge'){
			$out_trade_no = $this->_getIdFromItemId($out_trade_no);
			$uaccount = service('UserAccount')->get4UserById($out_trade_no);
			$_uid = $uaccount['uid'];
		}else{
			$error_msg='未知的支付项！';
		}
		//先录入支付记录。
		$ary_payinfo=array(	'trade_no'=>$trade_no
							,'pay_type'=>$itemType
		 					,'item_id'=>$out_trade_no
							,'total_fee'=>$total_fee
		 					,'service'=>$pay_mode
		 					,'return_info'=>$serialize_return_info
		 					,'paytime'=>time()
		  					,'uid'=>$_uid
		 				);
		if($itemType=='pay_charge')$ary_payinfo['sub_pay_type']='charge_cash';
		//判断是否金额相同，否则不处理
		//现金账户充值时不判断金额是否一致
		//现金账户不能对现金账户充值
		if(!($pay_mode=='xxypay'&&$itemType=='pay_charge')){
			if($itemType=='pay_charge'||($total_fee+$_total_pay)>=$order['paid_money']){
				$result = service('Pay')->addPayInfo($ary_payinfo);
			}else{
				$result['status']=0;
				$result['msg']='支付金额：'.$total_fee.'元，应付金额：'.$order['paid_money'].'元，不一致！';
			}	
		}else{
			$result['status']=0;
			$result['msg']='不能用现金账户进行充值！';
		}
		$result['PayInfo']=$ary_payinfo;
		$result['msg']=$result['msg'].''.$error_msg;
		return $result;
	}
	
	
	private function _getIdFromItemId($itemId){
		$itemId1  = explode('_',$itemId);
		return $itemId1[0];
	}
	
	//服务初始化
	public function init() {
	}

	//运行服务，系统服务自动运行
	public function run() {
	}
	
	/* 后台管理相关方法 */

	//启动服务，未编码
	public function _start(){
		return true;
	}
	
	//停止服务，未编码
	public function _stop(){
		return true;
	}

	//卸载服务，未编码
	public function _install(){
		return true;
	}

	//卸载服务，未编码
	public function _uninstall(){
		return true;
	}
}
?>